const bcrypt = require('bcryptjs')
const moment = require('moment')
const redisClient = require('../../../helper/redisClient')
const ResponseError = require('../../../helper/ResponseError')
const generateRandomHash = require('../../../helper/generateRandomHash')
const {
  ACCESS_TOKEN_EXPIRATION_ADMIN,
} = require('../../../config')
const { AUTHENTICATION } = require('../../../constant/RedisKey')
const { ADMINISTRATOR } = require('../../../constant/Role')

const tableName = 'administrator'
const accessTokenTableName = 'access_token'

const createAccessToken = async (knex, params) => {
  const {
    email,
    password,
    app,
    app_version: appVersion,
    device,
    device_version: deviceVersion,
  } = params
  const record = await knex.table(tableName).where({ email: email.toLowerCase() }).first()
  if (!record) {
    return Promise.reject(new ResponseError.InvalidLoginEmail())
  }
  if (!record.enabled) {
    return Promise.reject(new ResponseError.InvalidLoginUser())
  }
  const isPasswordIdentical = bcrypt.compareSync(password, record.password)
  if (!isPasswordIdentical) {
    return Promise.reject(new ResponseError.InvalidLoginPassword())
  }
  const token = generateRandomHash()
  const expirationTime = moment.utc().add(ACCESS_TOKEN_EXPIRATION_ADMIN, 'm')
  // create a record in db
  await knex.service.create(accessTokenTableName, {
    administrator_id: record.id,
    token,
    expired_at: expirationTime.format('YYYY-MM-DD HH:mm:ss'),
    app,
    app_version: appVersion,
    device,
    device_version: deviceVersion,
  })
  // create a record in redis
  const redisKey = `${AUTHENTICATION}${token}`
  const redisValue = `${ADMINISTRATOR}_${record.id}`
  redisClient.addRecord(redisKey, redisValue, ACCESS_TOKEN_EXPIRATION_ADMIN * 60)
  return token
}

module.exports = {
  createAccessToken,
}
